﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Windows.Forms;
using System.IO;
using System.Data.OleDb;
using System.Data;
using MyClass;

namespace GPS_DB
{
    class RecData
    {
        private struct RecDataLine
        {
            public string rd;
            public string dp;
            public string md;
            public string[] st;
            public string[] ph;
        }

        private struct SaveSetting
        {
            public bool allSt;
            public bool fb;
            public bool st;
            public bool ph;
            public bool rd;
        }

        ArrayList inValidTail = new ArrayList();
        ArrayList exp = new ArrayList();
        ArrayList wrongName = new ArrayList();

        ArrayList lines = new ArrayList();
        ArrayList lineErr = new ArrayList();
        ArrayList allST = new ArrayList();
        ArrayList allPH = new ArrayList();
        ArrayList allDP = new ArrayList();
        ArrayList allRD = new ArrayList();
        ArrayList allMD = new ArrayList();

        ArrayList stVisited = new ArrayList();
        ArrayList phVisited = new ArrayList();
        ArrayList rdVisited = new ArrayList();
        ArrayList dpVisited = new ArrayList();
        ArrayList mdVisited = new ArrayList();

        ArrayList mdbErr = new ArrayList();

        ArrayList myDB = new ArrayList();


        private string OpeningFilename;
        private string SavingFilename;
        private bool roadlockFlag;
        private string savingFolder;

        long starttick;

        SaveSetting ss = new SaveSetting();

        #region User Method
        public RecData()
        {
            readInMyDB();
            readInErrRcvry();
            ss.allSt = false;
            ss.fb = true;
            ss.st = true;
            ss.ph = true;
            ss.rd = true;

            savingFolder = Application.StartupPath + @"\RecDataReport\";
            if (!Directory.Exists(savingFolder))
            {
                Directory.CreateDirectory(savingFolder);
            }
        }
        public RecData(bool all, bool fb, bool st, bool ph, bool rd)
        {
            readInMyDB();
            readInErrRcvry();
            ss.allSt = all;
            ss.fb = fb;
            ss.st = st;
            ss.ph = ph;
            ss.rd = rd;

            savingFolder = Application.StartupPath + @"\RecDataReport\";
            if (!Directory.Exists(savingFolder))
            {
                Directory.CreateDirectory(savingFolder);
            }
        }
        public void AnalysisOneRecTxt()
        {
            Clear();
            OpenFileDialog frm1 = new OpenFileDialog();
            frm1.Filter = "txt file(*.txt)|*.txt";
            frm1.Title = "Please select simulation data! ";
            frm1.Multiselect = false;
            frm1.InitialDirectory = LrnS.GetItem("singleRecAnalysis");
            if (frm1.ShowDialog() == DialogResult.OK)
            {
                LrnS.SaveItem("singleRecAnalysis", Path.GetDirectoryName(frm1.FileName));
                starttick = DateTime.Now.Ticks;
                #region read
                using (StreamReader fs = new StreamReader(frm1.FileName, Encoding.Default))
                {
                    OpeningFilename = Path.GetFileName(frm1.FileName);

                    SavingFilename = savingFolder + "分析报告　" + Path.GetFileName(frm1.FileName);

                    string str = "";
                    while (true)
                    {
                        str = fs.ReadLine();
                        if (str == null)
                            break;
                        readInLine(str);
                    }
                    fs.Close();
                }
                #endregion

                frontBackCheck();
                if (mdbCheck(frm1.FileName))
                {
                    if (File.Exists(SavingFilename))
                        File.Delete(SavingFilename);
                    addsaving(SavingFilename);
                    System.Diagnostics.Process.Start(SavingFilename);
                }
            }
        }
        public void AnalysisMulRecTxt()
        {
            SavingFilename = savingFolder + "分析报告.txt";
            if (File.Exists(savingFolder + "分析报告.txt"))
            {
                File.Delete(savingFolder + "分析报告.txt");
            }

            OpenFileDialog frm1 = new OpenFileDialog();
            frm1.Filter = "txt file(*.txt)|*.txt";
            frm1.Title = "Please select Rec data! ";
            frm1.Multiselect = true;
            frm1.InitialDirectory = LrnS.GetItem("MulRecAnalysis");
            if (frm1.ShowDialog() == DialogResult.OK)
            {
                LrnS.SaveItem("MulRecAnalysis", Path.GetDirectoryName(frm1.FileName));
                starttick = DateTime.Now.Ticks;
                foreach (string fn in frm1.FileNames)
                {
                    #region read
                    Clear();
                    using (StreamReader fs = new StreamReader(fn, Encoding.Default))
                    {
                        OpeningFilename = Path.GetFileName(fn);

                        string str = "";
                        while (true)
                        {
                            str = fs.ReadLine();
                            if (str == null)
                                break;
                            readInLine(str);
                        }
                        fs.Close();
                    }
                    #endregion

                    frontBackCheck();
                    if (mdbCheck(fn))
                    {
                        addsaving(SavingFilename);
                    }
                }
            }
            else
            {
                return;
            }
            System.Diagnostics.Process.Start(SavingFilename);
            MessageBox.Show("生成完成！ \r\n用时：" +
                        ((DateTime.Now.Ticks - starttick) / 10000000).ToString() + "." +
                        ((DateTime.Now.Ticks - starttick) % 10000000).ToString() + "秒"
                        , ".Gps数据库");
        }
        #endregion

        #region Inner Method
        private void Clear()
        {
            OpeningFilename = "";
            roadlockFlag = false;

            stVisited.Clear();
            phVisited.Clear();
            rdVisited.Clear();
            dpVisited.Clear();
            mdVisited.Clear();
            mdbErr.Clear();
            lines.Clear();
            lineErr.Clear();
            allST.Clear();
            allPH.Clear();
            allDP.Clear();
            allRD.Clear();
            allMD.Clear();
        }
        private void readInLine(string readStr)
        {
            if (readStr.Length>100)
            {
                string[] st = new string[4];
                string[] ph = new string[4];
                string dp = "", rd = "", md = "";
                st[0] = PartString(readStr, "站1:");
                st[1] = PartString(readStr, "站2:");
                st[2] = PartString(readStr, "站3:");
                st[3] = PartString(readStr, "站4:");
                ph[0] = PartString(readStr, "电话1:");
                ph[1] = PartString(readStr, "电话2:");
                ph[2] = PartString(readStr, "电话3:");
                ph[3] = PartString(readStr, "电话4:");

                rd = readStr.Substring(0, readStr.IndexOf(' ')).Trim();
                dp = readStr.Substring(readStr.IndexOf(' ') + 1);
                dp = dp.Substring(0, dp.IndexOf(' ')).Trim();
                md = PartString(readStr, "模:");

                #region Add recs
                RecDataLine l = new RecDataLine();
                l.st = new string[4];
                l.ph = new string[4];
                l.rd = rd;
                l.dp = dp;
                l.md = md;
                for (int i = 0; i < 4; i++)
                {
                    l.st[i] = st[i];
                    l.ph[i] = ph[i];
                }
                if (lines.Count > 0)
                {
                    RecDataLine t = (RecDataLine)lines[lines.Count - 1];
                    if (l.st[0] != t.st[0] || l.st[1] != t.st[1] || l.st[2] != t.st[2] || l.st[3] != t.st[3] ||
                        l.ph[0] != t.ph[0] || l.ph[1] != t.ph[1] || l.ph[2] != t.ph[2] || l.ph[3] != t.ph[3] ||
                        l.rd != t.rd || l.dp != t.dp || l.md != t.md)
                    {
                        lines.Add(l);
                    }
                }
                else
                {
                    lines.Add(l);
                }
                #endregion

                #region add dispatch
                if (!allDP.Contains(dp))
                {
                    allRD.Add(rd);
                    allDP.Add(dp);
                    allMD.Add(md);
                }
                else if ((string)allRD[allDP.IndexOf(dp)] != rd || (string)allMD[allDP.IndexOf(dp)] != md)
                {
                    allRD.Add(rd);
                    allDP.Add(dp);
                    allMD.Add(md);
                }
                #endregion

                #region Add station
                for (int i = 3; i >= 0; i--)
                {
                    if (st[i] != "" && ph[i] != "")
                    {
                        int j = 0;
                        for (j = 0; j < allST.Count; j++)
                        {
                            if ((string)allST[j] == st[i] && (string)allPH[j] == ph[i])
                            {
                                break;
                            }
                        }
                        if (j == allST.Count)
                        {
                            allST.Add(st[i]);
                            allPH.Add(ph[i]);
                        }
                    }
                }
                #endregion

            }
        }
        private string PartString(string source,string part)
        {
            string resulat = "";
            int index = source.IndexOf(part);
            if (index >= 0)
            {
                int length = source.IndexOf(' ', index + part.Length) - index;
                if (length > 0)
                {
                    resulat = source.Substring(index, length);
                    resulat = resulat.Substring(part.Length).Trim();
                }
                else
                {
                    resulat = source.Substring(index).Trim();
                    resulat = resulat.Substring(part.Length).Trim();
                }
            }
            return resulat;
        }
        private void frontBackCheck()
        {
            RecDataLine r1, r2;
            for (int i = 0; i < lines.Count - 1; i++)
            {
                r1 = (RecDataLine)lines[i];
                r2 = (RecDataLine)lines[i + 1];

                string[] str1 = GetFrontBackST(r1);
                string[] str2 = GetFrontBackST(r2);

                #region 经过的车站
                if (str1[1] != "车站")
                {
                    stVisited.Add(str1[1]);
                    phVisited.Add(str1[4]);
                    rdVisited.Add(r1.rd);
                    dpVisited.Add(r1.dp);
                    mdVisited.Add(r1.md);
                    roadlockFlag = true;
                }
                if (str2[1] != "车站" && i == lines.Count - 2)
                {
                    stVisited.Add(str2[1]);
                    phVisited.Add(str2[4]);
                    rdVisited.Add(r2.rd);
                    dpVisited.Add(r2.dp);
                    mdVisited.Add(r2.md);
                }
                #endregion

                #region right
                if (r1.rd == r2.rd && r1.dp != r2.dp && r1.md != r2.md &&
                    r1.st[0] == r2.st[0] && r1.st[1] == r2.st[1] && r1.st[2] == r2.st[2] && r1.st[3] == r2.st[3] &&
                    r1.ph[0] == r2.ph[0] && r1.ph[1] == r2.ph[1] && r1.ph[2] == r2.ph[2] && r1.ph[3] == r2.ph[3])
                {
                    lineErr.Add("[切换]");
                    continue;
                }
                if (str1[1] == "车站" && str2[1] == "车站" && !roadlockFlag && str1[2] == str2[2])
                {
                    lineErr.Add("[开车]");
                    continue;
                }

                if (str1[1] == "车站" && str1[2] == str2[2] && str1[0] == str2[1])
                {
                    lineErr.Add("[入站]");
                    continue;
                }

                if (str1[1] != "车站" && str1[0] == str2[0] && str1[1] == str2[2])
                {
                    lineErr.Add("[出站]");
                    continue;
                }
                #endregion

                #region Error
                if (str1[1] == "车站" && str2[1] == "车站" && str1[0] == str2[2])
                {
                    lineErr.Add("{-----越过车站}");
                    continue;
                }

                if (str1[1] == "车站" && str2[1] == str1[2] && str1[0] == str2[0] && i > 0)
                {
                    string[] str0 = GetFrontBackST((RecDataLine)lines[i - 1]);
                    if (str0[2] == str2[2])
                    {
                        lineErr.Add("{-----列车调头}");
                        continue;
                    }
                    else
                    {
                        lineErr.Add("error>>>>>>>>>列车回头错误");
                        continue;
                    }
                }

                if (i == lines.Count - 2 && str1[0] == "" && str1[1] == str2[2] && str2[0] == str1[2])
                {
                    lineErr.Add("{-----已到达终点}");
                    continue;
                }
                #endregion

                lineErr.Add("error>>>>>>>>>错误类型未知");
            }
        }
        private string[] GetFrontBackST(RecDataLine st)
        {
            string[] result = new string[6];
            result.Initialize();
            if (st.st[3] == "车站")
            {
                result[0] = st.st[2];
                result[1] = st.st[3];
                result[2] = "";
                result[3] = st.ph[2];
                result[4] = st.ph[3];
                result[5] = "";
            }
            else
            {
                result[0] = st.st[1];
                result[1] = st.st[2];
                result[2] = st.st[3];
                result[3] = st.ph[1];
                result[4] = st.ph[2];
                result[5] = st.ph[3];
            }
            return result;
        }
        private string stationCheck(string st, string ph, string rd, string dp, string md)
        {
            if (st == "")
                return "";
            if (stVisited.Contains(st))
            {
                int index = stVisited.IndexOf(st);

                if ((ph != "" && (string)phVisited[index] != ph) || (ph == "" && (string)phVisited[index] != "00000000"))
                {
                    if (ss.ph)
                        return st.PadLeft(5, '　') + "(电话错误:txt电话" + (string)phVisited[index] + "  mdb电话" + ph + ")";
                    else
                        return "";
                }
                else if ((string)rdVisited[index] != rd || (string)dpVisited[index] != dp || (string)mdVisited[index] != md)
                {
                    if (ss.rd)
                        return st.PadLeft(5, '　') +
                            "(线路错误:txt" +
                            ((string)rdVisited[index]).PadLeft(5, '　') +
                            ((string)dpVisited[index]).PadLeft(8, '　') +
                            ((string)mdVisited[index]).PadLeft(4, ' ') +
                           "  <====>mdb" +
                           rd.PadLeft(5, '　') + dp.PadLeft(8, '　') + md.PadLeft(4, ' ') + ")";
                    else
                        return "";
                }
                else
                    return "";
            }
            else
            {
                if (ss.st)
                {
                    string adStr = "";
                    if (myDB.Contains("-" + rd + "-" + st + "-"))
                        adStr = "数据库中包含此站，但列车未经过";
                    return st.PadLeft(5, '　') + "(缺少此站)" + adStr;
                }
                else
                    return "";
            }
        }
        private bool mdbCheck(string recFile)
        {
            string road = getRoadName(recFile);
            string direction = getDirection(recFile);
            if (direction == "error")
            {
                MessageBox.Show("记录文件同时包含上行下行字样，请确认！", OpeningFilename);
                return false;
            }
            string mdbname = GF.FindFile(Application.StartupPath + "\\Primary Data", road, direction, ".mdb");
            if (mdbname != null)
            {
                readInMdb(mdbname);
                return true;
            }
            else
            {
                #region open mdb manually
                OpenFileDialog openFile_mdb = new OpenFileDialog();
                openFile_mdb.Filter = "数据库(.mdb)|*.mdb";
                openFile_mdb.Title = OpeningFilename;
                openFile_mdb.Multiselect = false;
                openFile_mdb.InitialDirectory = Application.StartupPath;
                if (openFile_mdb.ShowDialog() == DialogResult.OK)
                {
                    readInMdb(openFile_mdb.FileName);
                    return true;
                }
                return false;
                #endregion
            }
        }
        private void readInMdb(string filename)
        {
            string addressStr = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filename;
            OleDbConnection conn = new OleDbConnection(addressStr);
            OleDbDataAdapter dscmd = new OleDbDataAdapter();
            DataSet resultdataset = new DataSet();

            string strselect = "Select 所属线路名称,所属区段名称,工作模式,车站名称,车站电话号码 From export Order By 序号 Asc";
            OleDbCommand selectcommand = new OleDbCommand(strselect, conn);
            selectcommand.CommandType = CommandType.Text;

            try
            {
                conn.Open();

                dscmd.SelectCommand = selectcommand;
                int numrows = dscmd.Fill(resultdataset, "export");

                if (numrows > 0)
                {
                    string st, ph, rd, dp, md;
                    for (int i = 0; i < numrows; i++)
                    {
                        st = resultdataset.Tables["export"].Rows[i]["车站名称"].ToString().Trim();
                        ph = resultdataset.Tables["export"].Rows[i]["车站电话号码"].ToString().Trim();
                        rd = resultdataset.Tables["export"].Rows[i]["所属线路名称"].ToString().Trim();
                        dp = resultdataset.Tables["export"].Rows[i]["所属区段名称"].ToString().Trim();
                        md = resultdataset.Tables["export"].Rows[i]["工作模式"].ToString().Trim();
                        md = (int.Parse(md)).ToString();
                        st = stNameRecovery(rd, st);
                        string namecheck = stationCheck(st, ph, rd, dp, md);
                        if (namecheck != "")
                            mdbErr.Add(namecheck);
                    }
                }
                else
                {
                    MessageBox.Show("未找到有效数据！");
                }
            }
            catch (Exception er)
            {
                MessageBox.Show(er.Message.ToString());
            }
            finally
            {
                conn.Close();
            }
        }
        private string getRoadName(string recFilePath)
        {
            recFilePath = Path.GetFileName(recFilePath);
            string str = recFilePath;
            str = str.Substring(str.IndexOf("REC") + 3);
            if (str.IndexOf(" ") > 0)
            {
                str = str.Remove(str.IndexOf(" "));
            }
            if (str.IndexOf("(") > 0)
            {
                str = str.Remove(str.IndexOf("("));
            }
            if (str.IndexOf("（") > 0)
            {
                str = str.Remove(str.IndexOf("（"));
            }
            if (str.IndexOf("R") > 0)
            {
                str = str.Remove(str.IndexOf("R"));
            }
            if (str.IndexOf("r") > 0)
            {
                str = str.Remove(str.IndexOf("r"));
            }
            str = str.Trim();
            return str;
        }
        private string getDirection(string recFilePath)
        {
            string filename = Path.GetFileName(recFilePath);
            if (filename.Contains("上行"))
            {
                if (filename.Contains("下行"))
                    return "error";
                else
                    return "上行";
            }
            else if (filename.Contains("下行"))
            {
                return "下行";
            }
            return "";
        }
        private void readInErrRcvry()
        {
            inValidTail.Clear();
            exp.Clear();
            wrongName.Clear();
            string filename = Application.StartupPath + @"\temp\station name error recovery.txt";
            if (!File.Exists(filename))
                return;
            int secFlag = 0;
            using (StreamReader fs = new StreamReader(filename, Encoding.Default))
            {
                string str = "";
                while (true)
                {
                    str = fs.ReadLine();
                    if (str == null)
                        break;
                    str = str.Trim();
                    if (str.Contains(';'))
                        str = str.Remove(str.IndexOf(';'));
                    if (str == "#Redundant Tail")
                    {
                        secFlag = 1;
                        continue;
                    }
                    if (str == "#exception for Redundant Tail")
                    {
                        secFlag = 2;
                        continue;
                    }
                    if (str == "#wrong to right")
                    {
                        secFlag = 3;
                        continue;
                    }
                    if (str == "#end")
                    {
                        secFlag = 0;
                        continue;
                    }
                    switch (secFlag)
                    {
                        case 1:
                            if (str != "")
                                inValidTail.Add(str);
                            break;
                        case 2:
                            if (str != "")
                                exp.Add(str);
                            break;
                        case 3:
                            if (str != "")
                                wrongName.Add(str);
                            break;
                        default:
                            break;
                    }
                    
                }
                fs.Close();
            }
        }
        private string stNameRecovery(string rd, string st)
        {
            if (st == "")
                return st;
            string result = st;
            for (int i = 0; i < inValidTail.Count; i++)
            {
                if (exp.Contains(result))
                    break;

                string tail=(string)inValidTail[i];
                if (result.EndsWith(tail))
                {
                    result = result.Remove(result.IndexOf(tail));
                    break;
                }
            }

            for (int i = 0; i < wrongName.Count; i++)
            {
                string rdanst = "-" + result + "-" + rd + "-";
                string str = (string)wrongName[i];
                if (str.Contains(rdanst))
                {
                    result = str.Remove(0, rdanst.Length);
                }
            }

            return result;
        }
        private void readInMyDB()
        {
            myDB.Clear();
            string filedir = Application.StartupPath + "\\temp\\" + "record.txt";
            if (!File.Exists(filedir))
                return;
            string dbPath = "";
            using (TextReader fs = File.OpenText(filedir))
            {
                string str1 = "";
                str1 = fs.ReadLine().Trim();
                fs.Close();
                if (str1.EndsWith(".xls") && File.Exists(str1))
                {
                    dbPath = str1;
                }
            }
            if (dbPath == "")
                return;
            DataSet ds = GF.DsFromExcel(dbPath);
            if (!ds.Tables.Contains("车站$"))
                return;
            for (int i = 0; i < ds.Tables["车站$"].Rows.Count; i++)
            {
                string rd = ds.Tables["车站$"].Rows[i][0].ToString().Trim();
                string st = ds.Tables["车站$"].Rows[i][3].ToString().Trim();
                if (rd == "")
                    break;
                if (!st.EndsWith("*"))
                {
                    myDB.Add("-" + rd + "-" + st + "-");
                }

            }
            
        }
        #endregion

        #region saving
        private void addsaving(string dir)
        {
            using (FileStream fs = new FileStream(SavingFilename, FileMode.OpenOrCreate))
            {
                TextWriter wt = new StreamWriter(fs, Encoding.Default);
                fs.Seek(0, SeekOrigin.End);

                wt.WriteLine("***************************《" + OpeningFilename + "》分析报告********************************");

                if (ss.allSt)
                {
                    wt.WriteLine("txt所有车站电话：");
                    for (int i = 0; i < allST.Count; i++)
                    {
                        wt.WriteLine(allST[i].ToString().PadLeft(5, '　') + "—" + allPH[i].ToString());
                    }

                    wt.WriteLine("\r\ntxt所有线路调度区段：");
                    for (int i = 0; i < allRD.Count; i++)
                    {
                        wt.WriteLine(allRD[i].ToString().PadLeft(5, '　') + "—" + allDP[i].ToString().PadLeft(10, '—') +
                                     "—" + allMD[i].ToString());
                    }
                }

                if (ss.fb)
                {
                    wt.WriteLine("\r\n前后站检查：");
                    wt.WriteLine("序号　　线路　　　　　　区段　　模式　　　站一　　　站二　　　站三　　　站四　　结果");
                    for (int i = 0; i < lines.Count; i++)
                    {
                        RecDataLine t = (RecDataLine)lines[i];
                        wt.Write(i.ToString().PadLeft(3, '0') +
                                        t.rd.PadLeft(5, '　') + t.dp.PadLeft(10, '　') + t.md.PadLeft(4, ' ') +
                                        t.st[0].PadLeft(5, '　') + t.st[1].PadLeft(5, '　') +
                                        t.st[2].PadLeft(5, '　') + t.st[3].PadLeft(5, '　'));
                        if (i < lineErr.Count)
                            wt.Write("    " + (string)lineErr[i]);
                        wt.Write("\r\n");
                    }
                }

                if (ss.st || ss.rd || ss.ph)
                {
                    if (mdbErr.Count > 0)
                    {
                        wt.WriteLine("\r\n（车站　电话　线路　区段　模式）检查：");
                        for (int i = 0; i < mdbErr.Count; i++)
                        {
                            wt.WriteLine(mdbErr[i]);
                        }
                    }
                }
                wt.Close();
                fs.Close();
            }
        }
        #endregion

        //*****************************************************************************************************************
    }
}
